package com.tinem.platform.web.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.tinem.platform.module.pojo.co.GatewayHeadName;
import com.tinem.platform.module.pojo.co.RedisKeyEnum;
import com.tinem.platform.module.pojo.enums.security.EncryptionAlgorithm;
import com.tinem.platform.web.gateway.util.GatewayUtil;
import com.tinem.platform.web.gateway.util.MDCUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * @author fengzhihao
 * @version v1
 * @program: platform
 * @className ChannelScopeGatewayFilterFactory
 * @description 客户端返回数据加密
 * @site
 * @company
 * @create 2020-07-03 12:26
 */
@Slf4j
@Component
public class ClientResCryptoGatewayFilterFactory extends ModifyResponseBodyGatewayFilterFactory {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    @SuppressWarnings("unchecked")
    public GatewayFilter apply(ModifyResponseBodyGatewayFilterFactory.Config c) {
        ModifyResponseBodyGatewayFilterFactory.Config config = new ModifyResponseBodyGatewayFilterFactory.Config();
        config.setRewriteFunction(String.class,String.class,(exchange,resBody)-> {
            MDCUtil.set(exchange);
            //记录返回体
            log.debug("res body:{}",resBody);
            String gatewayRequestId = GatewayUtil.getReq(exchange);
            if(StrUtil.isNotBlank(resBody)){
                exchange.getAttributes().put(GatewayHeadName.X_PLATFORM_GATEWAY_RES_BODY,resBody);
            }


            String client = GatewayUtil.getClient(exchange);
            String clientRedisKey = RedisKeyEnum.client_info.getKey(client);

            // 缓存中客户端返回是否加密
            String  resCrypto = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "resCrypto");
            if(!Boolean.parseBoolean(resCrypto)){
                return Mono.just(resBody);
            }

            // 缓存中返回的加密类型
            String resCryptoType = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "resCryptoType");
            // 缓存中返回加密证书
            String resCryptoPpk = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "resCryptoPpk");
            // 缓存中返回加密KEY
            String resCryptoKey = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "resCryptoKey");
            // 缓存中返回加密IV
            String resCryptoIv = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "resCryptoIv");
            String body = EncryptionAlgorithm.valueOf(resCryptoType).encrypt(resCryptoKey,resCryptoIv,resCryptoPpk,resBody);
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_CRYPTO_TYPE,resCryptoType);

            return Mono.just(body);
        });
        return super.apply(config);
    }

}
